/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { ITaskContext, ImportRewriteOptions, Logger } from '../..';
import { GeneratedFileInfo, ImportRewriteService as IImportRewriteService } from '../types/ImportRewriteTypes';
import { ImportTransformServiceImpl } from './ImportTransformService';
import SerializationPathUtil from '../../utils/SerializationPathUtil';

/**
 * 导入重写主服务实现
 * 协调扫描策略和转换服务
 */
export class ImportRewriteServiceImpl implements IImportRewriteService {
  private readonly transformService: ImportTransformServiceImpl;

  constructor() {
    this.transformService = new ImportTransformServiceImpl();
  }

  /**
   * 重写项目中的导入语句
   * @param context 任务上下文
   * @param generatedFileInfos 生成文件信息列表
   * @param options 导入重写选项
   */
  rewriteImports(
    context: ITaskContext,
    generatedFileInfos: GeneratedFileInfo[],
    options: ImportRewriteOptions
  ): void {
    // 1. 扫描找到需要修改的文件
    const filesToUpdate = this.scanFilesWithModelImports(options.scanPaths, generatedFileInfos, context);

    if (filesToUpdate.length === 0) {
      Logger.info('未找到需要重写导入的文件');
      return;
    }

    Logger.info(`找到 ${filesToUpdate.length} 个文件需要重写导入`);

    // 2. 为每个文件重写导入语句
    let successCount = 0;
    let errorCount = 0;

    for (const filePath of filesToUpdate) {
      try {
        this.transformService.rewriteFileImports(
          filePath,
          context,
          generatedFileInfos,
          options.preserveOriginalImports
        );
        successCount++;
      } catch (error: any) {
        errorCount++;
      }
    }

    Logger.info(`导入重写完成: 成功 ${successCount} 个，失败 ${errorCount} 个`);
  }

  /**
   * 扫描找到包含模型导入的文件
   * @param scanPaths 扫描路径列表
   * @param generatedFileInfos 生成文件信息列表
   * @param context 任务上下文
   * @returns 需要更新的文件路径列表
   */
  private scanFilesWithModelImports(
    scanPaths: string[],
    generatedFileInfos: GeneratedFileInfo[],
    context: ITaskContext
  ): string[] {
    const filesToUpdate: string[] = [];

    for (const scanPath of scanPaths) {
      const absoluteScanPath = SerializationPathUtil.isAbsolute(scanPath)
        ? scanPath
        : SerializationPathUtil.pathResolve(context.getModulePath(), scanPath);

      if (!SerializationPathUtil.exist(absoluteScanPath)) {
        Logger.warn(`扫描路径不存在: ${absoluteScanPath}`);
        continue;
      }

      const files = SerializationPathUtil.scanEtsFiles(absoluteScanPath);

      // 过滤出可能包含需要重写导入的文件
      for (const filePath of files) {
        if (this.shouldCheckFile(filePath, generatedFileInfos)) {
          filesToUpdate.push(filePath);
        }
      }
    }

    // 添加Index.ets文件
    const IndexFilePath = SerializationPathUtil.pathResolve(context.getModulePath(), 'Index.ets');
    if (SerializationPathUtil.exist(IndexFilePath)) {
      filesToUpdate.push(IndexFilePath);
    }

    return filesToUpdate;
  }

  /**
   * 判断文件是否应该被检查
   * 排除生成的文件本身
   */
  private shouldCheckFile(filePath: string, generatedFileInfos: GeneratedFileInfo[]): boolean {
    // 排除生成文件目录中的文件
    return !generatedFileInfos.some(info =>
      filePath.startsWith(SerializationPathUtil.dirname(info.generatedFilePath))
    );
  }
}